#include #include #include #include #if defined(MSGLIDE) || defined (WTGLIDE) #include #endif #include #define WIN32_LEAN_AND_MEAN #include #include #include "winutil.h" #define TITLE "Egerter Software 3Dfx ScreenSaver" /* Forward declarations */ HWND hWndMain; HINSTANCE hInstance; /* My instance handle */ char ** commandLineToArgv(LPSTR lpCmdLine, int *pArgc); void PRGUI_InitPath (char *startpath); /* The following variables are used to simulate the input routines from WGT 5.1 */ char kbdon[256]; static int keyhead = 0; static int keytail = 0; static int keyqueue[256] = {0}; PR_MouseCallback_data mouse; int PR_mx0, PR_my0, PR_mx1, PR_my1; /* Direct Input */ #define WM_SYNCACQUIRE (WM_USER + 0) LPDIRECTINPUT g_pdi = NULL; LPDIRECTINPUTDEVICE g_pMouse; LPDIRECTINPUTDEVICE g_pKeyboard; HANDLE g_hevtMouse; int PR_AppActive; int fKeybdAcquired; int minit (void) { HRESULT err; GUID guid = GUID_SysMouse; if (g_pdi == NULL) { err = DirectInputCreate(hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); if(FAILED(err)) { MessageBox(NULL, "Unable to Create DirectInput Object", TITLE, MB_OK); return FALSE; } } /* Obtain an interface to the system mouse device. */ err = g_pdi->lpVtbl->CreateDevice(g_pdi, &guid, &g_pMouse, NULL); if (FAILED(err)) { MessageBox(NULL, "Unable to Create DirectInput Mouse Device", TITLE, MB_OK); return FALSE; } /* Set the data format to "mouse format". */ err = g_pMouse->lpVtbl->SetDataFormat(g_pMouse, &c_dfDIMouse); if (FAILED(err)) { MessageBox(NULL, "Unable to Set Mouse Format", TITLE, MB_OK); return FALSE; } /* Set the cooperativity level. */ err = g_pMouse->lpVtbl->SetCooperativeLevel(g_pMouse, hWndMain, DISCL_EXCLUSIVE | DISCL_FOREGROUND); if (FAILED(err)) { MessageBox(NULL, "Unable to Set Cooperative Level", TITLE, MB_OK); return FALSE; } PR_mx0 = 0; PR_my0 = 0; PR_mx1 = 639; PR_my1 = 479; mouse.mx = 320; mouse.my = 240; mouse.but = 0; return TRUE; } void mdeinit (void) { if (g_pdi) g_pdi ->lpVtbl->Release(g_pdi), g_pdi = NULL; if (g_pMouse) g_pMouse->lpVtbl->Release(g_pMouse), g_pMouse = NULL; } void msetbounds (int x0, int y0, int x1, int y1) { PR_mx0 = x0; PR_my0 = y0; PR_mx1 = x1; PR_my1 = y1; } void msetxy (int x0, int y0) { mouse.mx = x0; mouse.my = y0; } void noclick (void) { while (mouse.but) UpdateMessages (); } void PR_ReadMouse (void) { DIMOUSESTATE diMouseState; if (PR_AppActive) { if (g_pMouse->lpVtbl->GetDeviceState(g_pMouse, sizeof(diMouseState), &diMouseState) == DI_OK) { mouse.mx += (int)diMouseState.lX; mouse.my += (int)diMouseState.lY; mouse.but = (diMouseState.rgbButtons[0]>0) + ((diMouseState.rgbButtons[1]>0)<<1) + ((diMouseState.rgbButtons[2]>0)<<2); } } /* Clip the cursor to our client area */ if (mouse.mx < PR_mx0) mouse.mx = PR_mx0; if (mouse.mx > PR_mx1) mouse.mx = PR_mx1; if (mouse.my < PR_my0) mouse.my = PR_my0; if (mouse.my > PR_my1) mouse.my = PR_my1; } void PR_MouseSyncAcquire (HWND hwnd) { if (PR_AppActive) { if (g_pMouse) g_pMouse->lpVtbl->Acquire(g_pMouse); } else { if (g_pMouse) g_pMouse->lpVtbl->Unacquire(g_pMouse); } // InvalidateCursorRect(hwnd); } int installkbd (void) { GUID guid = GUID_SysKeyboard; HRESULT err; if (g_pdi == NULL) { err = DirectInputCreate(hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); if(FAILED(err)) { MessageBox(NULL, "Unable to Create DirectInput Object", TITLE, MB_OK); return FALSE; } } /* Obtain an interface to the system mouse device. */ err = g_pdi->lpVtbl->CreateDevice(g_pdi, &guid, &g_pKeyboard, NULL); if (FAILED(err)) { MessageBox(NULL, "Unable to Create DirectInput Keyboard Device", TITLE, MB_OK); return FALSE; } /* Set the data format to "mouse format". */ err = g_pKeyboard->lpVtbl->SetDataFormat(g_pKeyboard, &c_dfDIKeyboard); if (FAILED(err)) { MessageBox(NULL, "Unable to Set Keyboard Format", TITLE, MB_OK); return FALSE; } /* Set the cooperativity level. */ err = g_pKeyboard->lpVtbl->SetCooperativeLevel(g_pKeyboard, hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); if (FAILED(err)) { MessageBox(NULL, "Unable to Set Keyboard Cooperative Level", TITLE, MB_OK); return FALSE; } // try to acquire the keyboard err = g_pKeyboard->lpVtbl->Acquire(g_pKeyboard); if(SUCCEEDED(err)) { // keyboard was acquired fKeybdAcquired = TRUE; } else { // keyboard was NOT acquired fKeybdAcquired = FALSE; } // if we get here, all objects were created successfully return TRUE; } /* * * DI_ReadKeys * * Use DirectInput to read game-play keys * */ void PR_ReadKeyboard(void) { HRESULT hRes; if (g_pKeyboard == NULL) return; hRes = g_pKeyboard->lpVtbl->GetDeviceState(g_pKeyboard, sizeof(kbdon), kbdon); if(hRes != DI_OK) { if(hRes == DIERR_INPUTLOST) { // we lost control of the keyboard, reacquire fKeybdAcquired = FALSE; if(SUCCEEDED(g_pKeyboard->lpVtbl->Acquire(g_pKeyboard))) { fKeybdAcquired = TRUE; } } // failed to read the keyboard, just return return; } } void uninstallkbd (void) { if(fKeybdAcquired) { g_pKeyboard->lpVtbl->Unacquire(g_pKeyboard); fKeybdAcquired = FALSE; } if(g_pKeyboard != NULL) g_pKeyboard->lpVtbl->Release(g_pKeyboard); g_pKeyboard = NULL; } BOOL PR_KeyboardSyncAcquire (void) { // try to acquire the keyboard if(g_pKeyboard != NULL) { g_pKeyboard->lpVtbl->Acquire(g_pKeyboard); } else { // keyboard device has not been created. fKeybdAcquired = FALSE; return FALSE; } // if we get here, we are acquired again fKeybdAcquired = TRUE; return TRUE; } long FAR PASCAL MainWndproc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; LRESULT lRc; switch( message ) { case WM_SETCURSOR: SetCursor(NULL); return 0; break; case WM_KEYDOWN: if(!fKeybdAcquired) { keyqueue[keyhead++] = wParam & 0xFF; keyhead &= 255; return 0; } break; case WM_KEYUP: return 0; break; case WM_ACTIVATE: { WORD fActive = LOWORD(wParam); BOOL fMinimized = (BOOL) HIWORD(wParam); if ( ( fActive == WA_INACTIVE ) || fMinimized ) { #if defined(MSGLIDE) || defined(WTGLIDE) grSstControl (GR_CONTROL_DEACTIVATE); PR_AppActive = FALSE; PR_MouseSyncAcquire (hWnd); #endif } else { #if defined(MSGLIDE) || defined(WTGLIDE) grSstControl (GR_CONTROL_ACTIVATE); PR_AppActive = TRUE; #endif PR_MouseSyncAcquire(hWnd); PR_KeyboardSyncAcquire(); SetForegroundWindow (hWnd); } } break; case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: PR_AppActive = FALSE; PR_MouseSyncAcquire(hWnd); PR_KeyboardSyncAcquire(); break; case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: PR_AppActive = GetActiveWindow() == hWnd; PostMessage(hWnd, WM_SYNCACQUIRE, 0, 0L); break; case WM_SYNCACQUIRE: PR_MouseSyncAcquire (hWnd); PR_KeyboardSyncAcquire(); break; case WM_CREATE: break; case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); return 1; case WM_CLOSE: keyqueue[keyhead++] = 'q'; keyhead &= 255; break; case WM_DESTROY: PostQuitMessage (0); break; case WM_MOVE: #if defined(MSGLIDE) || defined(WTGLIDE) if (!grSstControl(GR_CONTROL_MOVE)) { PostMessage( hWnd, WM_CLOSE, 0, 0 ); return 0; } #endif break; case WM_SYSCOMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case SC_SCREENSAVE: break; default: lRc = DefWindowProc(hWnd, message, wParam, lParam); break; } if (IsWindow(hWnd)) { PR_MouseSyncAcquire (hWnd); PR_KeyboardSyncAcquire(); } return lRc; case WM_DISPLAYCHANGE: case WM_SIZE: { extern void getWindowSize(float *width, float *height); float width, height; getWindowSize(&width, &height); } #if defined(MSGLIDE) || defined(WTGLIDE) if (!grSstControl(GR_CONTROL_RESIZE)) { PostMessage(hWnd, WM_CLOSE, 0, 0 ); return 0; } #endif break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); } /* MainWndproc */ /* * initApplication * * Do that Windows initialization stuff... */ void PRGUI_LoadCursor3Dx (void); static BOOL initApplication( HANDLE hInstance, int nCmdShow ) { WNDCLASS wc; BOOL rc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MainWndproc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION); /* generic icon */ wc.hCursor = NULL; //LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = GetStockObject( BLACK_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = "WinGlideClass"; rc = RegisterClass( &wc ); if( !rc ) { return FALSE; } hWndMain = CreateWindowEx( WS_EX_TOPMOST, "WinGlideClass", TITLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | /* so we get an icon in the tray */ WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE, /* so we don't have to call ShowWindow */ //WS_POPUP | /* non-app window */ CW_USEDEFAULT, CW_USEDEFAULT, 600, /* GetSystemMetrics(SM_CXSCREEN), */ 40, /* GetSystemMetrics(SM_CYSCREEN), */ NULL, NULL, hInstance, NULL ); if (!hWndMain) return FALSE; if (!minit ()) { DestroyWindow(hWndMain); return 0; } ShowWindow (hWndMain, SW_NORMAL); UpdateWindow (hWndMain); BringWindowToTop (hWndMain); SetFocus (hWndMain); PR_AppActive = TRUE; PR_MouseSyncAcquire (hWndMain); return TRUE; } /* initApplication */ /* * WinMain */ int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { LPSTR realcommand; if( !initApplication(hInstance, nCmdShow) ) return FALSE; { int argc; char **argv; #ifdef __WATCOMC__ extern int WatMain(int argc, char **argv); #else extern int main(int argc, char **argv); #endif realcommand = GetCommandLine (); argv = commandLineToArgv(realcommand, &argc); // PRGUI_InitPath (argv[0]); #ifdef __WATCOMC__ WatMain (argc, argv); #else main (argc, argv); #endif } mdeinit (); DestroyWindow(hWndMain); return 0; } /* WinMain */ /* * Converts lpCmdLine to WinMain into argc, argv */ static char *argvbuf[32]; static char cmdLineBuffer[1024]; char ** commandLineToArgv(LPSTR lpCmdLine, int *pArgc) { char *p, *pEnd; int argc = 0; if (lpCmdLine == NULL) { *pArgc = argc; return argvbuf; } strcpy(cmdLineBuffer, lpCmdLine); p = cmdLineBuffer; pEnd = p + strlen(cmdLineBuffer); if (pEnd >= &cmdLineBuffer[1022]) pEnd = &cmdLineBuffer[1022]; fflush (stdout); while (1) { /* skip over white space */ fflush(stdout); while (*p == ' ') p++; if (p >= pEnd) break; while (*p == '\"') p++; if (p >= pEnd) break; argvbuf[argc++] = p; if (argc >= 32) break; /* skip till there's a 0 or a white space */ while (*p && (*p != ' ')) p++; if (*p == ' ') *p++ = 0; if (*p == '\"') *p++ = 0; } *pArgc = argc; return argvbuf; } void getWindowSize(float *width, float *height) { RECT rect; GetClientRect(hWndMain, &rect); *width = (float) rect.right; *height = (float) rect.bottom; } /* This dispatches any messages waiting and waits in a loop if the application is not active. */ void UpdateMessages (void) { MSG msg; PR_ReadMouse (); PR_ReadKeyboard (); do { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } while (!PR_AppActive); } char PR_getch (void) { MSG msg; char rv; if (keytail != keyhead) { rv = keyqueue[keytail++]; keytail &= 255; return rv; } while (GetMessage( &msg, NULL, 0, 0 )) { TranslateMessage (&msg); DispatchMessage (&msg); if (keytail != keyhead) { rv = keyqueue[keytail++]; keytail &= 255; return rv; } } return rv; } int PR_kbhit (void) { MSG msg; if (keyhead != keytail) return 1; while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); /* this might change keyhead */ if (keyhead != keytail) return 1; } return 0; }